Predicción curva COVID-19 Región de Murcia

Metodología

Imports necesarios para la correcta ejecución del Notebook.

Importación y análisis exploratorio

Lectura del conjunto de datos obtenido de la pagina de salud de Murcia https://www.murciasalud.es/pagina.php?id=458869 Recogidos desde el 08/03/2020 hasta el dia 25/03/2020.

Renombramos los nombres de algunas de las columnas para que queden mas compactos.

Convertimos los datos leidos en un dataFrame y lo mostramos para ver su apariencia.

Lo siguiente que haremos es indexar el dataframe por la columna 'Fecha'. Para ello, primero debemos convertir la misma en un objeto de tipo DatatimeIndex. Usamos la funcion 'to_datetime' y le indicamos el formato en el que se encuentran las fechas para que se lea y procese bien. Posteriormente eliminamos la columna del dataFrame e insertamos el nuevo DatatimeIndex como íncide. Finalmente mostramos el resultado.

Con la siguiente función eliminamos todos aquellos valores que se almacenan o completan como NaN.

Sumando sintomáticos y asintomáticos

Sumamos asintomáticos y sintomáticos que estaban repartidos en tres grupos de edades. Eliminamos los grupos y nos quedamos con el total de cada uno en dos nuevas columnas del dataframe.

A continuación lo que hacemos es guardarla en un archivo de extensión .csv para poder recuperarla posteriormente.

Añadiendo Movilidad

Necesitamos añadir los datos de movilidad proporcionados por el Ministerio de Transporte y Movilidad en la Región de Murcia. Para ello se buscaron los códigos de los municipios murcianos así como sus correspondientes códigos para el Ministerio, ya que no siempre coinciden.

A continuación se definen las funciones necesarias para el correcto tratamiento de los datos.

La siguiente función permite parsear las fechas, a partir del nombre del fichero obtenemos la fecha correspondiente

Al igual que hicimos con el dataframe de los datos de salud que leímos al principio, debemos transformar las fechas en objetos de tipo DatatimeIndex. Posteriormente las ordenaremos para que se muestren en orden cronológico. Para ello usamos la función 'to_datetime', que convierte nuestra lista de fechas en DatatimeIndex. Acto seguido creamos el dataframe con las entradas, las salidas a la Región de Murcia y las fechas y las ponemos como índice del dataframe. Ahora solo queda ordenarlo. Añadimos tres columnas adicionales al dataframe que son los meses, dias y años de las fechas. Ordenamos según estos valores y posteriormente las eliminamos del dataframe. Devolvemos el dataframe construido.

La lista "codigos" contiene todos los códigos de los municipios de la Región con la codificación usada por el Ministerio.

Lo siguiente que haremos es procesar todos los datos que tenemos. Para cada archivo, nos quedamos con las salidas y entradas en la Región de Murcia, esto es, no se considera la movilidad entre distintos municipios murcianos si no las salidas y entradas de municipios fuera de la Región hacia ella o desde municipios de la Región hasta municipios fuera de ella.

Convertimos los datos recogidos en un dataframe mediante la función definida anteriormente.

Vemos ahora el número de filas y el número de missing values.

Guardamos el conjunto de datos con la movilidad en un nuevo archivo con extensión csv.

Juntando los datos

En este apartado se juntan los dataframe de las dos fuentes de datos que se han procesado. De esta forma, a los datos de salud se le añaden los datos de movilidad generando un nuevo dataframe, que será con el que trabajaremos el resto del proyecto.

Aparecen nuevos valores missing, debido a las diferentes fechas sobre las que se han recogido los datos.

Suprimimos los missing values.

Guardamos en archivo de extensión csv el dataframe.

Contamos de nuevo las filas y el número de missing values y los eliminamos.

Visualización de series

Matriz de correlación

La matriz de correlación se presenta en forma de ''mapa de calor''. Los valores más violetas muestran una mayor correlación entre las correspondientes series de datos, mientras que los valores más claros (azules) muestran una menor correlación.

Transformaciones en los datos

Transformamos los datos que hemos recogido en secciones anteriores. En primer lugar creamos los dataframes con variables retrasadas (lag3 y lag5). Posteriormente realizamos una normalización de los datos.

Creación de variables retrasadas

La siguiente función crea un predictor con el lag que se le pase como parámetro sobre el conjunto de datos.

Creamos dos predictores, uno con lag3 y otro con lag5

Guardamos.

Guardamos.

Normalización de los predictores

Utilizamos la función MaxMinScaler para normalizar el conjunto de datos entre 0 y 1.

Escalamos los predictores de lag3 y lag5 calculados anteriormente

Evaluación

Predicción incidentes

Imports necesarios para la ejecución.

Usamos la validación cruzada para series temporales con 10 pliegues.

La siguiente función busca los mejores hiperparámetros usando como medida de error RMSE.

Cálculo de errores MAE, RMSE.

Calculamos el coeficiente de corrrelación de Pearson dados un conjunto de test y unas predicciones. Añadimos estos valores obtenidos a la lista pasada como parámetro. Usamos la función 'np.corrcoef' que devuelve la matriz de correlación. Basta con quedarnos con la esquina superior derecha de la matriz, ya que esta es simétrica.

Función para calcular la gráfica de comparación entre incidentes reales y predecidos en el instante t+i.

Las dos siguientes funciones realizan el cálculo de las predicciones en los pasos adelante a partir de un modelo, una predicción y un conjunto de test dados. La primera sirve para el caso Lag = 3 y la segunda para el caso Lag = 5.

Función para calcular los errores y las gráficas asociadas a las predicciones calculadas en la función anterior.

Visualización de todas las predicciones juntas en cada paso adelante.

División del conjunto de datos

Dividimos el conjunto de datos con una distribución 80% para train y 20% para test sin perder la temporalidad.

El caso de lag3 el conjunto de datos es de 355x28. El 80% de las filas son 355x0'8 = 284 mientras que el 20% son 355x0'2 = 71 así que tendremos 284 muestras para train y 71 para test.

En el caso de lag5 el conjunto de datos es de 353x28. El 80% de las filas son 353x0'8 = 282'4 -> 282 mientras que el 20% son 353x0'2 = 70'6 así que por el redondeo, tendremos 282 muestras para train y 71 para test.

Configuración y predicción de los modelos

Random Forest

Creamos una instancia del modelo.

Lo siguiente que hacemos es hacer la búsqueda de hiperparámetros, para ello usaremos GridSearchCV, que prueba todas las posibles combinaciones de parámetros que se le pase usando validación cruzada. Veamos cuáles son los hiperparámetros de RF y sus valores por defecto.

Generamos un grid que posteriormente pasaremos a la función de búsqueda.

Lag 3

Buscamos el mejor ajuste de hiperparámetros.

Seleccionamos el mejor modelo entrenado.

Los mejores hiperparámetros obtenidos tras el ajuste son:

Tabla con los resultados para cada combinación de parámetros.

Guardamos el modelo obtenido.

Cargamos el modelo.

Predicción t

Realizamos un predict sobre el conjunto de test con el mejor ajuste de Random Forest para Lag3.

Creamos tres nuevas listas. Las dos primeras para los errores RMSE y MAE y la tercera para los CC calculados. Añadimos los errores RMSE y MAE de la predicción.

Mostramos la gráfica incidentes reales VS incidentes predecidos en la predicción un paso adelante.

Predicción 7 días adelante

Calculamos las predicciones en los 7 días adelante.

Mostramos en una gráfica todas las predicciones y los incidentes reales.

Calculamos los errores y los vamos añadiendo a la lista de errores. Además se muestran las predicciones en cada instante.

Añadimos los errores RMSE y MAE y después calculamos los CC de cada predicción en pasos adelante.

Lag 5

Predicción t

Predicción 7 días adelante

Linear Regression

Creamos una instancia del modelo.

Lag 3

En este caso no hace falta hacer búsqueda de hiperparámetros. Lo único que hay que hacer es entrenar el modelo.

Predicción t

Predicción 7 días adelante

Creamos una lista donde irán las predicciones t+i con i = 1,...,7

Calculamos las gráficas de las predicciones así como los errores

Lag 5

Predicción t

Predicción 7 días adelante

SVR

Lag 3

Predicción t

Predicción 7 días adelante

Lag 5

Predicción t

Predicción 7 días adelante

Lasso

Fórmula a minimizar -> (1 / (2 n_samples)) ||y - Xw||^2_2 + alpha * ||w||_1

Lag 3

Predicción t

Predicción 7 días adelante

Lag 5

Predicción t

Predicción 7 días adelante

Gradient Boosting Regressor

La idea de este modelo es construir árboles en serie de forma que un árbol posterior intenta corregir los errores de todos los anteriores. Parámetros importantes son la profundidad de los árboles, cuándo hacer pre-prunning (útil para evitar el overfitting) y también el ratio de aprendizaje o learning_rate que controla como se esfuerza el árbol actual en corregir los errores de los árboles anteriores. También podemos aumentar el número de árboles con el parámetro n_estimators. Al contrario que en random forest, usar un número de árboles muy alto en gradient llevará a un modelo mucho más complejo que puede caer en overfitting. Max_depth suele variar entre 1 y 5.

Lag 3

Predicción t

Predicción 7 días adelante

Lag 5

Predicción t

Predicción 7 días adelante

Elastic Net

Minimiza la función objetivo:

1 / (2 n_samples) ||y - Xw||^2_2 + alpha l1_ratio ||w||_1 + 0.5 alpha (1 - l1_ratio) * ||w||^2_2 =

a ||w||_1 + 0.5 b * ||w||_2^2 donde

alpha = a + b y l1_ratio = a / (a + b)

Lag 3

Predicción t

Predicción 7 días adelante

Lag 5

Predicción t

Predicción 7 días adelante

Tablas de errores

En este apartado se crean las tablas de errores para todos los modelos. Se generan dos tablas:

  1. Errores en cada uno de los pliegues de la validación cruzada sobre el conjunto de train (80% de los datos).
  2. Errores en las predicciones (t+i con i = 0,...,7) sobre el conjunto de test (20% de los datos).

Validación cruzada conjunto Train

Para cada uno de los modelos hemos obtenido los mejores hiperparámetros. Entrenamos los modelos usando validación cruzada de 10 pliegues (time series) y obteniendo para cada pliegue los errores RMSE, MAE y CC.

Las medidas de error que queremos obtener de los pliegues son RMSE y MAE.

Como se sigue un proceso de maximización (sigue el criterio de que valores más altos son mejores) entonces devuelve los errores con el signo cambiado. Simplemente multiplicando por -1 obtenemos el resultado.

Listas para añadir los errores de los splits para cada modelo en cada lag.

Una vez obtenidos todos los errores para cada uno de los modelos entonces creamos 6 dataframes, uno por error, tres para lag3 y otros tres para lag5. Las columnas son los modelos y las filas son los resultados de cada uno de los errores en los 10 pliegues.

Función para crear el dataframe con los errores de los pliegues sobre el conjunto de train.

Lista para guardar los coeficientes de correlación.

Para obtener los coeficientes de correlación en validación cruzada usamos la función split que devuelve un generador. Iterando sobre éste obtenemos los índices generados para los conjuntos de train y validación en cada split. Nos interesa saber la predicción que se hace sobre el conjunto de validación, así que nos quedamos con esos íncides. Como el array es de la forma ([indices_train],[indices_validacion]) cogemos el segundo elemento de cada array.

Para el caso de lag 3.

Obtenemos los conjuntos con los que haremos las predicciones y la predicción correspondiente.

Para el caso de lag 5.

Obtenemos, como hemos hecho con lag3, los conjuntos con los que haremos las predicciones.

Función para añadir los coeficientes de correlación calculados en cada split a una lista.

Repetimos el mismo procedimiento ahora para todos los modelos. Usamos la validación cruzada para obtener el RMSE y MAE. Los añadimos a las listas correspondientes de errores para posteriormente crear el dataframe. Hacemos lo mismo con el CC, calculado a partir de los conjuntos de validación y test que se crearon antes con los índices de los conjuntos.

Random Forest

Linear Regression

Lasso

SVR

Gradient Boosting Regressor

Elastic Net

Creación tablas validación cruzada

Una vez obtenidas todas las medidas de error entonces creamos la tabla. Creamos una tabla por cada métrica: una para RMSE, una para MAE y una para CC.

RMSE

Creamos los dataframes con los errores en los pliegues y los guardamos.

MAE

CC

Predicciones en Test

Ahora calculamos las otras tablas, las de los errores con las predicciones sobre el conjunto de test.

Las filas son las predicciones.

Función para crear el dataframe de los errores en las predicciones sobre el conjunto de test. Las columnas son los modelos y las filas las predicciones.

Ya podemos crear las tablas. De nuevo, generamos una tabla para cada métrica. Recordar que los errores en test ya fueron almacenados cuando se hizo la predicción de los modelos sobre el conjunto de test anteriormente. Solo tenemos que guardar todas las predicciones en una lista y generar el dataframe correspondiente con la función anterior.

RMSE

Añadimos los errores RMSE que se calcularon para cada modelo. Tendremos una lista de listas, donde habrá 12 elementos (todos los modelos) cuyos elementos son listas con 8 errores (las predicciones t+i con i = 0,...,7).

Se almacenan en un fichero de texto para no tener que realizar toda la ejecución de cálculo de errores.

Finalmente creamos el dataframe.

MAE

CC

Visualización gráficas sobre train

En este apartado final se visualizan las gráficas en los 7 pasos adelante generadas por la predicción sobre el conjunto de entrenamiento. Esto nos servirá para detectar posibles casos de overfitting.

Añadimos los modelos entrenados a una lista y generamos los nombres de los modelos para visualizar las gráficas.

Para cada modelo, predecimos sobre el conjunto de train (80% de los datos). Lo visualizamos y a partir de ese resultado, obtenemos las predicciones en los siete pasos adelante, tal y como hicimos con el conjunto de test mediante la función calcular_predicciones. Finalmente visualizamos las predicciones.